import pako from 'pako'
import { showloading, hideloading } from '../global/loading';
import { luckysheetrefreshgrid, jfrefreshgrid_rhcw } from '../global/refresh';
import editor from '../global/editor'
import { sheetHTML, luckyColor } from './constant';
import sheetmanage from './sheetmanage';
import menuButton from './menuButton';
import { createFilterOptions } from './filter';
import luckysheetFreezen from './freezen';
import luckysheetPostil from './postil';
import imageCtrl from './imageCtrl';
import dataVerificationCtrl from './dataVerificationCtrl';
import hyperlinkCtrl from './hyperlinkCtrl';
import { getObjType, replaceHtml, getByteLen } from '../utils/util';
import { getSheetIndex } from '../methods/get';
import Store from '../store';
import { collaborativeEditBox } from './select'
import locale from '../locale/locale';
import dayjs from "dayjs";
import json from '../global/json';
import luckysheetConfigsetting from './luckysheetConfigsetting';
import { customImageUpdate } from './imageUpdateCtrl';
import method from '../global/method';

const server = {
	gridKey: null,
	loadUrl: null,
	updateUrl: null,
	updateImageUrl: null,
	title: null,
	loadSheetUrl: null,
	retryTimer: null,
	allowUpdate: true, //共享编辑模式
	historyParam: function (data, sheetIndex, range) {
		let _this = this;

		let r1 = range.row[0], r2 = range.row[1];
		let c1 = range.column[0], c2 = range.column[1];

		if (r1 == r2 && c1 == c2) { //单个单元格更新
			let v = data[r1][c1];
			_this.saveParam("v", sheetIndex, v, { "r": r1, "c": c1 });
		}
		else { //范围单元格更新
			let rowlen = r2 - r1 + 1;
			let collen = c2 - c1 + 1;

			let timeR = Math.floor(1000 / collen);
			let n = Math.ceil(rowlen / timeR); //分批次更新，一次最多1000个单元格

			for (let i = 0; i < n; i++) {
				let str = r1 + timeR * i;

				let edr;
				if (i == n - 1) {
					edr = r2;
				}
				else {
					edr = r1 + timeR * (i + 1) - 1;
				}

				let v = [];

				for (let r = str; r <= edr; r++) {
					let v_row = [];

					for (let c = c1; c <= c2; c++) {
						if (data[r] == null) {
							v_row.push(null);
						}
						else {
							v_row.push(data[r][c]);
						}
					}

					v.push(v_row);
				}

				_this.saveParam("rv", sheetIndex, v, { "range": { "row": [str, edr], "column": [c1, c2] } });

				if (i == n - 1) {
					_this.saveParam("rv_end", sheetIndex, null);
				}
			}
		}
	},
	saveParam: function (type, index, value, params) {
		let _this = this;

		if (!_this.allowUpdate) {
			return;
		}

		if (value == undefined) {
			value = null;
		}

		let d = {};
		d.t = type;
		d.i = index;
		d.v = value;

		//切换sheet页不发后台，TODO：改为发后台+后台不广播
		if (type === 'shs') {
			return;
		}

		if (type == "rv") { //单元格批量更新
			d.range = params.range;
		}
		else if (type == "v" || type == "fu" || type == "fm") {
			d.r = params.r;
			d.c = params.c;
		}
		else if (type == "fc") {
			d.op = params.op;
			d.pos = params.pos;
		}
		else if (type == "drc" || type == "arc" || type == "h" || type == "wh") {
			d.rc = params.rc;
		}
		else if (type == "c") {
			d.cid = params.cid;
			d.op = params.op;
		}
		else if (type == "f") {
			d.op = params.op;
			d.pos = params.pos;
		}
		else if (type == "s") {

		}
		else if (type == "sh") {
			d.op = params.op;
			if (params.cur != null) {
				d.cur = params.cur;
			}
		}
		else if (type == "cg") {
			d.k = params.k;
		}
		else if (type == "all") {
			d.k = params.k;
			// d.s = params.s;
		}
		d.id = localStorage.getItem('socketId')
		d.username =localStorage.getItem('socketUserName')
		console.log('给socket发送数据并且是格式没有改变之前的d', d);

		// TODO 配置自定义方式同步图片
		const customImageUpdateMethodConfig = luckysheetConfigsetting.imageUpdateMethodConfig
		if (JSON.stringify(customImageUpdateMethodConfig) !== "{}") {
			if ("images" != d.k) {
				let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), { to: "string" });

				if (_this.websocket != null) {
					console.log('给socket发送数据22', msg);

					_this.websocket.send(msg);
				}
			} else {
				customImageUpdate(customImageUpdateMethodConfig.method, customImageUpdateMethodConfig.url, d)
					.then((data) => {
						console.log(data);
					})
					.catch((err) => {
						console.log(err);
					});

			}
		} else {


			let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), { to: "string" });
			// let msg = pako.deflate(encodeURIComponent(JSON.stringify(d)), { to: "string" });

			if (_this.websocket != null) {
				console.log('给socket发送数据', msg);

				_this.websocket.send(msg);
			}
		}

	},
	websocket: null,
	wxErrorCount: 0,
	openWebSocket: function () {
		let _this = this;

		if ('WebSocket' in window) {
			let wxUrl = _this.updateUrl + "?t=111&g=" + encodeURIComponent(_this.gridKey);
			if (_this.updateUrl.indexOf('?') > -1) {
				wxUrl = _this.updateUrl + "&t=111&g=" + encodeURIComponent(_this.gridKey);
			}

			_this.websocket = new WebSocket(wxUrl);

			//连接建立时触发
			_this.websocket.onopen = function () {
				console.info(locale().websocket.success);
				hideloading();
				_this.wxErrorCount = 0;

				//防止websocket长时间不发送消息导致断连
				_this.retryTimer = setInterval(function () {
					_this.websocket.send("rub");
				}, 60000);
			}

			//客户端接收服务端数据时触发
			_this.websocket.onmessage = function (result) {
				Store.result = result
				let data = new Function("return " + result.data)();
				method.createHookFunction('cooperativeMessage', data)
				console.info('onmessage返回的数据result和data', result, data);
				let type = data.type;
				console.log('data的type', type);
				let { message, id } = data;
				// 用户退出时，关闭协同编辑时其提示框
				if (message === '用户退出') {
					$("#luckysheet-multipleRange-show-" + id).hide();
					Store.cooperativeEdit.changeCollaborationSize = Store.cooperativeEdit.changeCollaborationSize.filter(value => {
						return value.id != id
					})
					Store.cooperativeEdit.checkoutData = Store.cooperativeEdit.checkoutData.filter(value => {
						return value.id != id
					})
				}
				if (type == 1) { //send 成功或失败
					const oldIndex = data.data.v.index;
					const sheetToUpdate = Store.luckysheetfile.filter((sheet) => sheet.index === oldIndex)[0];
					if (sheetToUpdate !== null) {
						setTimeout(() => {
							const index = data.data.i;
							sheetToUpdate.index = index;
							Store.currentSheetIndex = index;

							$(`#luckysheet-sheets-item${oldIndex}`).attr('data-index', index);
							$(`#luckysheet-sheets-item${oldIndex}`).prop('id', `luckysheet-sheets-item${index}`);
							$(`#luckysheet-datavisual-selection-set-${oldIndex}`).prop('id', `luckysheet-datavisual-selection-set-${index}`);
						}, 1);
					}
				}
				else if (type == 2) { //更新数据
					let item = JSON.parse(data.data);
					_this.wsUpdateMsg(item);
					let chang_data = JSON.parse(data.data)
					if (chang_data.k == 'columnlen') {
						collaborativeEditBox(chang_data.v, null)
					} else if (chang_data.k == 'rowlen') {
						collaborativeEditBox(null, chang_data.v)
					}
				}
				else if (type == 3) { //多人操作不同选区("t": "mv")（用不同颜色显示其他人所操作的选区）
					let id = data.id;
					let username = data.username;
					console.log('parse之前的item', data.data);
					let item = JSON.parse(data.data);
					console.log('serve.js:257@@#@#的item', item);
					let type = item.t,
						index = item.i,
						value = item.v;
					if (Store.cooperativeEdit.changeCollaborationSize.length === 0) {
						Store.cooperativeEdit.changeCollaborationSize.push({ id: id, v: item.v[0], i: index })
					}
					let flag = Store.cooperativeEdit.changeCollaborationSize.some(value1 => {
						return value1.id == id
					})
					if (flag) {
						Store.cooperativeEdit.changeCollaborationSize.forEach(val => {
							if (val.id == id) {
								val.v = item.v[0] || item.range[0]
								val.i = index
							}
						})
					} else {
						Store.cooperativeEdit.changeCollaborationSize.push({ id: id, v: item.v[0], i: index })
					}
					if (getObjType(value) != "array" && getObjType(value) !== "object") {
						value = JSON.parse(value);
					}
					let r = 0
					let c = 0
					if (index == Store.currentSheetIndex) {//发送消息者在当前页面

						if (getObjType(value) === "object" && value.op === 'enterEdit') {
							r = value.range[value.range.length - 1].row[0];
							c = value.range[value.range.length - 1].column[0];
							_this.multipleRangeShow(id, username, r, c, value.op);

						} else {

							r = value[value.length - 1].row[0];
							c = value[value.length - 1].column[0];

							_this.multipleRangeShow(id, username, r, c);

						}

					} else {
						if (getObjType(value) === "object" && value.op === 'enterEdit') {
							r = value.range[value.range.length - 1].row[0];
							c = value.range[value.range.length - 1].column[0];
						} else {
							r = value[value.length - 1].row[0];
							c = value[value.length - 1].column[0];
						}
					}

					if (Store.cooperativeEdit.checkoutData.length === 0) {
						if (value.op) {
							Store.cooperativeEdit.checkoutData.push({ id, username, r, c, op: value.op, index })
						} else {
							Store.cooperativeEdit.checkoutData.push({ id, username, r, c, index })
						}
					}
					let checkoutFlag = Store.cooperativeEdit.checkoutData.some(item => {
						return item.id == id
					})
					if (checkoutFlag) {
						Store.cooperativeEdit.checkoutData.forEach(item => {
							if (item.id == id) {
								item.username = username
								item.r = r
								item.c = c
								item.index = index
								if (value.op === 'enterEdit') {
									item.op = value.op
								}
							}
						})
					} else {
						if (value.op === 'enterEdit') {
							Store.cooperativeEdit.checkoutData.push({ id, username, r, c, op: value.op, index })
						} else {
							Store.cooperativeEdit.checkoutData.push({ id, username, r, c, index })
						}
					}

					//其他客户端切换页面时
					Store.cooperativeEdit.checkoutData.forEach(item => {
						if (item.index != Store.currentSheetIndex) {
							$("#luckysheet-multipleRange-show-" + item.id).hide();
							item.op == ''
						}
					})

					if ($("#luckysheet-multipleRange-show-" + id)[0]) {
						let change_bottom = $("#luckysheet-multipleRange-show-" + id)[0].offsetHeight - 1
						$("#luckysheet-multipleRange-show-" + id + ">.username").css({ "bottom": change_bottom + 'px' })
					}
				}
				else if (type == 4) { //批量指令更新
					// let items = JSON.parse(data.data);

					// After editing by multiple people, data.data may appear as an empty string
					let items = data.data === "" ? data.data : JSON.parse(data.data);

					for (let i = 0; i < items.length; i++) {
						_this.wsUpdateMsg(item[i]);
					}
				} else if (type == 5) {
					showloading(data.data);
				} else if (type == 6) {
					hideloading();
				}
			}

			//通信发生错误时触发
			_this.websocket.onerror = function () {
				_this.wxErrorCount++;

				if (_this.wxErrorCount > 3) {
					showloading(locale().websocket.refresh);
				}
				else {
					showloading(locale().websocket.wait);
					_this.openWebSocket();
				}
			}

			//连接关闭时触发
			_this.websocket.onclose = function (e) {
				console.info(locale().websocket.close);
				if (e.code === 1000) {
					clearInterval(_this.retryTimer)
					_this.retryTimer = null
				} else {
					alert(locale().websocket.contact);
				}
			}
		}
		else {
			alert(locale().websocket.support);
		}
	},
	wsUpdateMsg: function (item) {
		let type = item.t,
			index = item.i,
			value = item.v;

		let file = Store.luckysheetfile[getSheetIndex(index)];

		if (["v", "rv", "cg", "all", "fc", "drc", "arc", "f", "fsc", "fsr", "sh", "c"].includes(type) && file == null) {
			return;
		}

		if (type == "v") { //单个单元格数据更新
			if (file.data == null || file.data.length == 0) {
				return;
			}

			let r = item.r, c = item.c;
			file.data[r][c] = value;

			if (index == Store.currentSheetIndex) {//更新数据为当前表格数据
				Store.flowdata = file.data;
				editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

				//如果更新的单元格有批注
				if (value != null && value.ps != null) {
					luckysheetPostil.buildPs(r, c, value.ps);
				}
				else {
					luckysheetPostil.buildPs(r, c, null);
				}

				setTimeout(function () {
					luckysheetrefreshgrid();
				}, 1);
			}
		}
		else if (type == "rv") { //范围单元格数据更新
			if (Object.keys(item.range).length > 0) {
				Store.cooperativeEdit.merge_range = item.range
				Store.cooperativeEdit.merge_range.v = item.v
				collaborativeEditBox();
			}
			if (file.data == null || file.data.length == 0) {
				return;
			}

			let r1 = item.range.row[0], r2 = item.range.row[1];
			let c1 = item.range.column[0], c2 = item.range.column[1];

			for (let r = r1; r <= r2; r++) {
				for (let c = c1; c <= c2; c++) {
					file.data[r][c] = value[r - r1][c - c1];
				}
			}

			if (index == Store.currentSheetIndex) {//更新数据为当前表格数据
				Store.flowdata = file.data;
				editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

				//如果更新的单元格有批注
				for (let r = r1; r <= r2; r++) {
					for (let c = c1; c <= c2; c++) {
						if (value[r - r1][c - c1] != null && value[r - r1][c - c1].ps != null) {
							luckysheetPostil.buildPs(r, c, value[r - r1][c - c1].ps);
						}
						else {
							luckysheetPostil.buildPs(r, c, null);
						}
					}
				}

				setTimeout(function () {
					luckysheetrefreshgrid();
				}, 1);
			}
		}
		else if (type == "cg") { //config更新（rowhidden，rowlen，columnlen，merge，borderInfo）
			let k = item.k;

			if (k == "borderInfo") {
				file["config"]["borderInfo"] = value;
			}
			else {
				if (!(k in file["config"])) {
					file["config"][k] = {};
				}

				// for(let key in value){
				//     file["config"][k][key] = value[key];
				// }

				// ⚠️ 上面的处理方式会导致部分配置项被遗漏，以致协同编辑的时候多视图出现不一致的情况，调整处理的策略为直接替换配置项：
				// 可能的配置项为：
				// columnlen: {0: 65, 1: 186, 2: 52}
				// customHeight: {0: 1, 5: 1, 6: 1}
				// customWidth: {0: 1, 1: 1, 2: 1}
				// merge: {2_1: {…}, 4_2: {…}, 6_2: {…}}
				// rowlen: {0: 19, 5: 93, 6: 117}
				if (value && (typeof value == "object")) {
					file["config"][k] = value;
				}

			}

			if (index == Store.currentSheetIndex) {//更新数据为当前表格数据
				Store.config = file["config"];

				if (k == "rowlen" || k == "columnlen" || k == "rowhidden") {
					jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
				}

				setTimeout(function () {
					luckysheetrefreshgrid();
				}, 1);
			}
		}
		else if (type == "all") { //通用保存更新
			let k = item.k;
			file[k] = value;

			if (k == "name") { //工作表名
				$("#luckysheet-sheet-container-c #luckysheet-sheets-item" + index).find("span.luckysheet-sheets-item-name").html(value);
			}
			else if (k == "color") { //工作表颜色
				let currentSheetItem = $("#luckysheet-sheet-container-c #luckysheet-sheets-item" + index);
				currentSheetItem.find(".luckysheet-sheets-item-color").remove();

				if (value != null || value != "") {
					currentSheetItem.append('<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' + value + ';"></div>');
				}
			}
			else if (k == "pivotTable") { //PivotTable
				// luckysheet.pivotTable.changePivotTable(index);
			}
			else if (k == "frozen") { //freezen row and column

				// tranform frozen
				luckysheetFreezen.frozenTofreezen();

				if (index == Store.currentSheetIndex) {
					const _locale = locale();
					const locale_freezen = _locale.freezen;
					if (file["freezen"].horizontal == null) {
						$("#luckysheet-freezen-btn-horizontal").html('<i class="fa fa-list-alt"></i> ' + locale_freezen.freezenRow);
						luckysheetFreezen.freezenhorizontaldata = null;
						$("#luckysheet-freezebar-horizontal").hide();
					}
					else {
						luckysheetFreezen.createFreezenHorizontal(file["freezen"].horizontal.freezenhorizontaldata, file["freezen"].horizontal.top);
					}

					if (file["freezen"].vertical == null) {
						$("#luckysheet-freezen-btn-vertical").html('<i class="fa fa-indent"></i> ' + locale_freezen.freezenColumn);
						luckysheetFreezen.freezenverticaldata = null;
						$("#luckysheet-freezebar-vertical").hide();
					}
					else {
						luckysheetFreezen.createFreezenVertical(file["freezen"].vertical.freezenverticaldata, file["freezen"].vertical.left);
					}

					luckysheetFreezen.createAssistCanvas();
				}
			}
			else if (k == "filter_select") { //筛选范围
				if (index == Store.currentSheetIndex) {
					createFilterOptions(value);
				}
			}
			else if (k == "filter") { //筛选保存
				if (index == Store.currentSheetIndex) {
					createFilterOptions(file.filter_select, value);
				}
			}
			else if (k == "luckysheet_conditionformat_save") { //条件格式
				if (index == Store.currentSheetIndex) {
					setTimeout(function () {
						luckysheetrefreshgrid();
					}, 1);
				}
			}
			else if (k == "luckysheet_alternateformat_save") { //交替颜色
				if (index == Store.currentSheetIndex) {
					setTimeout(function () {
						luckysheetrefreshgrid();
					}, 1);
				}
			}
			else if (k == "config") { //config
				if (index == Store.currentSheetIndex) {
					Store.config = value;
					jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
				}
			}
			else if (k == "dynamicArray") { //动态数组
				if (index == Store.currentSheetIndex) {
					setTimeout(function () {
						luckysheetrefreshgrid();
					}, 1);
				}
			}
			else if (k == "images") { //图片
				if (index == Store.currentSheetIndex) {
					imageCtrl.images = value;
					imageCtrl.allImagesShow();
					imageCtrl.init();
				}
			}
			else if (k == "dataVerification") { //数据验证
				if (index == Store.currentSheetIndex) {
					dataVerificationCtrl.dataVerification = value;
					dataVerificationCtrl.init();
				}
			}
			else if (k == "hyperlink") { //链接
				if (index == Store.currentSheetIndex) {
					hyperlinkCtrl.hyperlink = value;
					hyperlinkCtrl.init();
				}
			}
		}
		else if (type == "fc") { //函数链calc
			let op = item.op, pos = item.pos;

			if (getObjType(value) != "object") {
				value = new Function("return " + value)();
			}

			let r = value.r, c = value.c;

			let calcChain = file["calcChain"] == null ? [] : file["calcChain"];

			if (op == "add") {
				calcChain.push(value);
			}
			else if (op == "del") {
				for (let a = 0; a < calcChain.length; a++) {
					if (r == calcChain[a].r && c == calcChain[a].c && index == calcChain[a].index) {
						calcChain.splice(a, 1);
					}
				}
			}
			// else if(op == "update"){
			//     for(let a = 0; a < calcChain.length; a++){
			//         if(r == calcChain[a].r && c == calcChain[a].c && index == calcChain[a].index){
			//             calcChain[a].func = func;
			//         }
			//     }
			// }

			setTimeout(function () {
				luckysheetrefreshgrid();
			}, 1);
		}
		else if (type == "drc") { //删除行列
			if (file.data == null || file.data.length == 0) {
				return;
			}

			let rc = item.rc,
				st_i = value.index,
				len = value.len,
				mc = value.mc,
				borderInfo = value.borderInfo;
			let data = file.data;

			if (rc == "r") {
				file["row"] -= len;

				data.splice(st_i, len);

				//空白行模板
				let row = [];
				for (let c = 0; c < data[0].length; c++) {
					row.push(null);
				}

				//删除多少行，增加多少行空白行
				for (let r = 0; r < len; r++) {
					data.push(row);
				}
			}
			else {
				file["column"] -= len;

				//空白列模板
				let addcol = [];
				for (let r = 0; r < len; r++) {
					addcol.push(null);
				}

				for (let i = 0; i < data.length; i++) {
					data[i].splice(st_i, len);

					data[i] = data[i].concat(addcol);
				}
			}

			for (let x in mc) {
				let r = mc[x].r, c = mc[x].c;
				data[r][c].mc = mc[x];
			}

			file["config"].merge = mc;
			file["config"].borderInfo = borderInfo;

			if (index == Store.currentSheetIndex) {
				Store.flowdata = data;
				editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

				Store.config["merge"] = mc;
				Store.config["borderInfo"] = borderInfo;

				setTimeout(function () {
					luckysheetrefreshgrid();
				}, 1);
			}
		}
		else if (type == "arc") { //增加行列
			if (file.data == null || file.data.length == 0) {
				return;
			}

			let rc = item.rc,
				st_i = value.index,
				len = value.len,
				addData = value.data,
				direction = value.direction,
				mc = value.mc,
				borderInfo = value.borderInfo;
			let data = $.extend(true, [], file.data);

			if (rc == "r") {
				file["row"] += len;

				//空行模板
				let row = [];
				for (let c = 0; c < data[0].length; c++) {
					row.push(null);
				}

				let arr = [];
				for (let i = 0; i < len; i++) {
					if (addData[i] == null) {
						arr.push(JSON.stringify(row));
					}
					else {
						arr.push(JSON.stringify(addData[i]));
					}
				}

				if (direction == "lefttop") {
					if (st_i == 0) {
						new Function("data", "return " + 'data.unshift(' + arr.join(",") + ')')(data);
					}
					else {
						new Function("data", "return " + 'data.splice(' + st_i + ', 0, ' + arr.join(",") + ')')(data);
					}
				}
				else {
					new Function("data", "return " + 'data.splice(' + (st_i + 1) + ', 0, ' + arr.join(",") + ')')(data);
				}
			}
			else {
				file["column"] += len;

				for (let i = 0; i < data.length; i++) {
					/* 在每一行的指定位置都插入一列 */
					for (let j = 0; j < len; j++) {
						if (direction == "lefttop") {
							data[i].splice(st_i, 0, addData[j]);
						} else {
							data[i].splice(st_i + 1, 0, addData[j]);
						}
					}
				}
			}

			for (let x in mc) {
				let r = mc[x].r, c = mc[x].c;
				data[r][c].mc = mc[x];
			}

			file.data = data;
			file["config"].merge = mc;
			file["config"].borderInfo = borderInfo;

			if (index == Store.currentSheetIndex) {
				Store.flowdata = data;
				editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

				Store.config["merge"] = mc;
				Store.config["borderInfo"] = borderInfo;

				setTimeout(function () {
					luckysheetrefreshgrid();
				}, 1);
			}
		}
		else if (type == "f") { //筛选
			let op = item.op, pos = item.pos;

			let filter = file.filter;

			if (filter == null) {
				filter = {};
			}

			if (op == "upOrAdd") {
				filter[pos] = value;
			}
			else if (op == "del") {
				delete filter[pos];
			}

			if (index == Store.currentSheetIndex) {
				createFilterOptions(file.filter_select, filter);
			}
		}
		else if (type == "fsc") { //清除筛选
			file.filter = null;
			file.filter_select = null;

			if (index == Store.currentSheetIndex) {
				$('#luckysheet-filter-selected-sheet' + Store.currentSheetIndex + ', #luckysheet-filter-options-sheet' + Store.currentSheetIndex).remove();
				$("#luckysheet-filter-menu, #luckysheet-filter-submenu").hide();
			}
		}
		else if (type == "fsr") { //恢复筛选
			file.filter = value.filter;
			file.filter_select = value.filter_select;

			if (index == Store.currentSheetIndex) {
				createFilterOptions(file.filter_select, file.filter);
			}
		}
		else if (type == "sha") { //新建sheet
			Store.luckysheetfile.push(value);

			let colorset = '';
			if (value.color != null) {
				colorset = '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' + value.color + ';"></div>';
			}

			$("#luckysheet-sheet-container-c").append(replaceHtml(sheetHTML, { "index": value.index, "active": "", "name": value.name, "style": "", "colorset": colorset }));
			$("#luckysheet-cell-main").append('<div id="luckysheet-datavisual-selection-set-' + value.index + '" class="luckysheet-datavisual-selection-set"></div>');

			// *添加sheet之后,要判断是否需要显示sheet滚动按钮
			sheetmanage.locationSheet()
		}
		else if (type == "shc") { //复制sheet
			let copyindex = value.copyindex, name = value.name;

			let copyarrindex = getSheetIndex(copyindex);
			let copyjson = $.extend(true, {}, Store.luckysheetfile[copyarrindex]);

			copyjson.index = index;
			copyjson.name = name;

			Store.luckysheetfile.splice(copyarrindex + 1, 0, copyjson);

			let copyobject = $("#luckysheet-sheets-item" + copyindex);
			$("#luckysheet-sheet-container-c").append(replaceHtml(sheetHTML, { "index": copyjson.index, "active": "", "name": copyjson.name, "style": "", "colorset": "" }));
			$("#luckysheet-sheets-item" + copyjson.index).insertAfter(copyobject);
			$("#luckysheet-cell-main").append('<div id="luckysheet-datavisual-selection-set-' + copyjson.index + '" class="luckysheet-datavisual-selection-set"></div>');
		}
		else if (type == "shd") { //删除sheet
			for (let i = 0; i < Store.luckysheetfile.length; i++) {
				if (Store.luckysheetfile[i].index == value.deleIndex) {

					// 如果删除的是当前sheet，则切换到前一个sheet页
					if (Store.currentSheetIndex === value.deleIndex) {
						const index = value.deleIndex;

						Store.luckysheetfile[sheetmanage.getSheetIndex(index)].hide = 1;

						let luckysheetcurrentSheetitem = $("#luckysheet-sheets-item" + index);
						luckysheetcurrentSheetitem.hide();

						$("#luckysheet-sheet-area div.luckysheet-sheets-item").removeClass("luckysheet-sheets-item-active");

						let indicator = luckysheetcurrentSheetitem.nextAll(":visible");
						if (luckysheetcurrentSheetitem.nextAll(":visible").length > 0) {
							indicator = indicator.eq(0).data("index");
						}
						else {
							indicator = luckysheetcurrentSheetitem.prevAll(":visible").eq(0).data("index");
						}
						$("#luckysheet-sheets-item" + indicator).addClass("luckysheet-sheets-item-active");

						sheetmanage.changeSheetExec(indicator);
					}

					server.sheetDeleSave.push(Store.luckysheetfile[i]);

					Store.luckysheetfile.splice(i, 1);

					break;
				}
			}

			$("#luckysheet-sheets-item" + value.deleIndex).remove();
			$("#luckysheet-datavisual-selection-set-" + value.deleIndex).remove();
			sheetmanage.locationSheet()

		}
		else if (type == "shr") { //sheet位置
			for (let x in value) {
				Store.luckysheetfile[getSheetIndex(x)].order = value[x];
			}
		}
		else if (type == "shre") { //删除sheet恢复操作
			for (let i = 0; i < server.sheetDeleSave.length; i++) {
				if (server.sheetDeleSave[i].index == value.reIndex) {
					let datav = server.sheetDeleSave[i];

					Store.luckysheetfile.push(datav);

					let colorset = '';
					if (value.color != null) {
						colorset = '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' + datav.color + ';"></div>';
					}

					$("#luckysheet-sheet-container-c").append(replaceHtml(sheetHTML, { "index": datav.index, "active": "", "name": datav.name, "style": "", "colorset": colorset }));
					$("#luckysheet-cell-main").append('<div id="luckysheet-datavisual-selection-set-' + datav.index + '" class="luckysheet-datavisual-selection-set"></div>');
					break;
				}
			}
		}
		else if (type == "sh") { //隐藏sheet
			let op = item.op, cur = item.cur;

			if (op == "hide") {
				file.hide = 1;
				$("#luckysheet-sheets-item" + index).hide();

				if (index == Store.currentSheetIndex) {
					$("#luckysheet-sheets-item" + cur).addClass("luckysheet-sheets-item-active");
					sheetmanage.changeSheetExec(cur);
				}
			}
			else if (op == "show") {
				file.hide = 0;
				$("#luckysheet-sheets-item" + index).show();
			}
			sheetmanage.locationSheet()
		}
		else if (type == "c") { //图表操作 TODO
			let op = item.op, cid = item.cid;

			if (op == "add") { //插入
				file.chart.push(value);

				luckysheet.insertChartTosheet(value.sheetIndex, value.dataSheetIndex, value.option, value.chartType, value.selfOption, value.defaultOption, value.row, value.column, value.chart_selection_color, value.chart_id, value.chart_selection_id, value.chartStyle, value.rangeConfigCheck, value.rangeRowCheck, value.rangeColCheck, value.chartMarkConfig, value.chartTitleConfig, value.winWidth, value.winHeight, value.scrollLeft1, value.scrollTop1, value.chartTheme, value.myWidth, value.myHeight, value.myLeft, value.myTop, value.myindexrank1, true);
			}
			else if (op == "xy" || op == "wh" || op == "update") { //移动 缩放 更新
				for (let i = 0; i < file.chart.length; i++) {
					let chartjson = file.chart[i];

					if (chartjson.chart_id == cid) {
						for (let item in chartjson) {
							for (let vitem in value) {
								if (item == vitem) {
									chartjson[item] = value[vitem];
								}
							}
						}

						sheetmanage.saveChart(chartjson);

						return;
					}
				}
			}
			else if (op == "del") { //删除
				for (let i = 0; i < file.chart.length; i++) {
					let chartjson = file.chart[i];

					if (chartjson.chart_id == cid) {
						file.chart.splice(i, 1);

						$("#" + cid).remove();
						sheetmanage.delChart($("#" + cid).attr("chart_id"), $("#" + cid).attr("sheetIndex"));

						return;
					}
				}
			}
		}
		else if (type == "na") { //表格名称
			$("#luckysheet_info_detail_input").val(value).css("width", getByteLen(value) * 10);
		}
	},
	multipleIndex: 0,
	multipleRangeShow: function (id, name, r, c, value) {
		let _this = this;
		const fullName = name;

		let row = Store.visibledatarow[r],
			row_pre = r - 1 == -1 ? 0 : Store.visibledatarow[r - 1],
			col = Store.visibledatacolumn[c],
			col_pre = c - 1 == -1 ? 0 : Store.visibledatacolumn[c - 1];

		let margeset = menuButton.mergeborer(Store.flowdata, r, c);
		if (!!margeset) {
			row = margeset.row[1];
			row_pre = margeset.row[0];

			col = margeset.column[1];
			col_pre = margeset.column[0];
		}

		// 超出16个字符就显示...
		if (getByteLen(name) > 16) {
			name = getByteLen(name, 16) + "...";
		}

		// 如果正在编辑，就显示“正在输入”
		if (value === 'enterEdit') {
			name += " " + locale().edit.typing;
		}

		if ($("#luckysheet-multipleRange-show-" + id).length > 0) {
			$("#luckysheet-multipleRange-show-" + id).css({ "position": "absolute", "left": col_pre - 1, "width": col - col_pre - 1, "top": row_pre - 1, "height": row - row_pre - 1 });

			$("#luckysheet-multipleRange-show-" + id + " .username").text(name);
			$("#luckysheet-multipleRange-show-" + id + " .username").show();

			if (Store.cooperativeEdit.usernameTimeout['user' + id] != null) {
				clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id])
			}
			Store.cooperativeEdit.usernameTimeout['user' + id] = setTimeout(() => {
				clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id]);
				Store.cooperativeEdit.usernameTimeout['user' + id] = null;
			}, 10 * 1000)



		}
		else {
			// let itemHtml = '<div id="luckysheet-multipleRange-show-'+ id +'" data-color="'+ luckyColor[_this.multipleIndex] +'" title="'+ name +'" style="position: absolute;left: '+ (col_pre - 1) +'px;width: '+ (col - col_pre - 1) +'px;top: '+ (row_pre - 1) +'px;height: '+ (row - row_pre - 1) +'px;border: 1px solid '+ luckyColor[_this.multipleIndex] +';z-index: 15;">'+
			//                 '<div style="width: 100%;height: 100%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;opacity: 0.03;background-color: '+ luckyColor[_this.multipleIndex] +'"></div>'+
			//                '</div>';

			let itemHtml = `<div
								id="luckysheet-multipleRange-show-${id}"
								class="luckysheet-multipleRange-show"
								data-color="${luckyColor[_this.multipleIndex]}"
								title="${fullName}"
								style="position: absolute;left: ${col_pre - 1}px;width: ${col - col_pre - 1}px;top: ${row_pre - 1}px;height: ${row - row_pre - 1}px;border: 1px solid ${luckyColor[_this.multipleIndex]};z-index: 15;">

								<div class="username" style="height: 19px;line-height:19px;width: max-content;position: absolute;bottom: ${row - row_pre - 1}px;right: 0;background-color: ${luckyColor[_this.multipleIndex]};color:#ffffff;padding:0 10px;">
								${name}
								</div>

								<div style="width: 100%;height: 100%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;opacity: 0.03;background-color: ${luckyColor[_this.multipleIndex]}">
								</div>

							</div>`;
			// 正在输入

			$(itemHtml).appendTo($("#luckysheet-cell-main #luckysheet-multipleRange-show"));

			_this.multipleIndex++;

			// 设定允许用户名消失的定时器，10秒后用户名可隐藏
			// 10秒之类，用户操作界面不会隐藏用户名；10秒之后如果用户操作了界面，则隐藏用户名，没操作就不隐藏
			if (Store.cooperativeEdit.usernameTimeout['user' + id] != null) {
				clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id])
			}
			Store.cooperativeEdit.usernameTimeout['user' + id] = setTimeout(() => {
				clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id]);
				Store.cooperativeEdit.usernameTimeout['user' + id] = null;
			}, 10 * 1000)
		}
	},
	sheetDeleSave: [], //共享编辑模式下 删除的sheet保存下来，方便恢复时取值
	submitInterval: 1000,
	imagesubmitInterval: 5000,
	submitdatalimit: 50,
	submitcompresslimit: 1000,
	checksubmit: function (data) {
		let _this = this;
		//clearTimeout(_this.requestTimeOut);

		_this.submitTimeout();

		clearTimeout(_this.imageRequestTimeout);
		_this.imageRequestTimeout = setTimeout(function () {
			_this.imageRequest();
		}, _this.imagesubmitInterval);
	},
	submitTimeout: function () {
		let _this = this;
		clearTimeout(_this.requestTimeOut);

		//console.log(_this.requestlast, dayjs(), (_this.requestlast!=null && _this.requestlast.add(10, 'seconds').isBefore(dayjs()) ) );
		if (!_this.requestLock && (_this.requestlast != null && _this.requestlast.clone().add(1, 'seconds').isBefore(dayjs()))) {
			_this.request();
		}

		// if(!_this.imageRequestLock && (_this.imageRequestLast==null || _this.imageRequestLast.clone().add(30, 'seconds').isBefore(dayjs()) ) ){

		// }

		_this.requestTimeOut = setTimeout(function () {
			_this.submitTimeout();
		}, _this.submitInterval);
	},
	requestLock: false,
	requestlast: null,
	firstchange: true,
	requestTimeOut: null,
	request: function () {
		let _this = this;
		let key = this.gridKey;
		let cahce_key = key + "__qkcache";

		_this.cachelocaldata(function (cahce_key, params) {
			if (params.length == 0) {
				return;
			}

			params = encodeURIComponent(JSON.stringify(params));
			let compressBeginLen = params.length;
			let iscommpress = false;
			// if (compressBeginLen > _this.submitcompresslimit) {
			//     params = pako.gzip(params, { to: "string" });
			//     iscommpress = true;
			// }
			_this.requestLock = true;
			//console.log(params);
			// console.log("request");
			if (_this.updateUrl != "") {
				$.post(_this.updateUrl, { compress: iscommpress, gridKey: _this.gridKey, data: params }, function (data) {
					let re = new Function("return " + data)();
					if (re.status) {
						$("#luckysheet_info_detail_update").html("最近存档时间:" + dayjs().format("M-D H:m:s"));
						$("#luckysheet_info_detail_save").html("同步成功");
						_this.clearcachelocaldata();
					}
					else {
						$("#luckysheet_info_detail_save").html("<span style='color:#ff2121'>同步失败</span>");
						_this.restorecachelocaldata();
					}
					_this.requestlast = dayjs();
					_this.requestLock = false;
				});
			}
		});
	},
	imageRequestLast: null,
	imageRequestLock: false,
	imageRequestTimeout: null,
	imageRequest: function () {
		let _this = this;

		html2canvas($("#" + container).find(".luckysheet-grid-window").get(0), {
			onrendered: function (canvas) {
				//let imgcut = $("#luckysheet-cell-main").find(".luckysheet-grid-window");
				//document.body.appendChild(canvas);
				let old = $(canvas).appendTo("body");
				old.hide();
				let newwidth = old.width();
				let newheight = old.height();
				let imageData = old.get(0).getContext("2d").getImageData(0, 0, newwidth, newheight);

				let cutW = newwidth, cutH = newheight;
				if (cutW * 0.54 > cutH) {
					cutW = cutH / 0.54;
				}
				else {
					cutH = cutW * 0.54;
				}
				let newCanvas = $("<canvas>").attr("width", cutW).attr("height", cutH)[0];

				newCanvas.getContext("2d").putImageData(imageData, 0, 0);

				old.attr("width", 350);
				old.attr("height", 189);
				old.get(0).getContext("2d").drawImage(newCanvas, 0, 0, 350, 189);
				let base64 = old.get(0).toDataURL('image/jpeg', 0.9);

				//console.log(base64);
				//console.log("压缩：", pako.gzip(base64, { to: "string" }));
				//console.log("imageRequest");
				let curindex = luckysheet.sheetmanage.getCurSheetnoset();
				_this.imageRequestLock = true;
				// let data1 = pako.gzip(encodeURIComponent(JSON.stringify({"t":"thumb", "img": base64, "curindex":curindex })), { to: "string" });
				let data1 = encodeURIComponent(JSON.stringify({ "t": "thumb", "img": base64, "curindex": curindex }));
				old.remove();
				//console.log("缩略图", _this.imageRequestLast,base64);
				if (_this.updateImageUrl != "") {
					// $.post(_this.updateImageUrl, { compress: true, gridKey: _this.gridKey, data:data1  }, function (data) {
					$.post(_this.updateImageUrl, { compress: false, gridKey: _this.gridKey, data: data1 }, function (data) {
						let re = new Function("return " + data)();
						if (re.status) {
							imageRequestLast = dayjs();
						}
						else {
							$("#luckysheet_info_detail_save").html("<span style='color:#ff2121'>网络不稳定</span>");
						}
						_this.imageRequestLock = true;
					});
				}

			}
		});
	},
	localdata: [],
	matchOpt: function (v, d) {
		for (let vitem in v) {
			if (vitem == "t" && v["t"] in { "drc": 1, "arc": 1, "sha": 1, "shc": 1, "shd": 1 }) {
				return false;
			}

			if (vitem == "v") {
				continue;
			}

			if (!(vitem in d)) {
				return false;
			}

			if (d[vitem] != v[vitem]) {
				return false;
			}
		}

		return true;
	},
	deleteRepeatOpt: function (data, value) {
		//let d = $.extend(true, [], data); //原来
		let d = data;
		let _this = this;

		if (value instanceof Array) {
			for (let i = 0; i < value.length; i++) {
				let vitem = value[i];

				for (let a = 0; a < d.length; a++) {
					let ditem = data[i]; //let ditem = data[a];?

					if (_this.matchOpt(vitem, ditem)) {
						delete d[a];
					}
				}
			}
		}
		else {
			for (let a = 0; a < d.length; a++) {
				let ditem = d[a];

				if (_this.matchOpt(value, ditem)) {
					delete d[a];
				}
			}
		}

		let ret = [];
		for (let i = 0; i < d.length; i++) {
			if (d[i] != null) {
				ret.push(d[i]);
			}
		}

		return ret;
	},
	setlocaldata: function (value, func) {
		let key = this.gridKey;
		//store.push(key, data);
		let _this = this;
		_this.getlocaldata(function (data) {
			if (data == null) {
				data = [];
			}

			//此处不去重，在request同步后台时统一循环一次去重
			//let data = _this.deleteRepeatOpt(data, value);

			if (value instanceof Array) {
				data = data.concat(value);
			}
			else {
				data.push(value);
			}

			_this.localdata = data;
			func(_this.localdata);

			//console.log(value);
			// localforage.setItem(key, data).then(function () {
			//     console.log(data);
			//     func(data);
			// }).catch(function (err) {

			// });
		});
	},
	getlocaldata: function (func) {
		let key = this.gridKey;
		//return store.get(key);
		func(this.localdata);
		// localforage.getItem(key).then(function(readValue) {
		//     func(readValue);
		// });
	},
	clearlocaldata: function (func) {
		let key = this.gridKey;
		//store.remove(key);
		this.localdata = [];
		func();
		// localforage.removeItem(key, function(err,value) {
		//     func();
		// });
	},
	cachelocaldata: function (func) {
		let key = this.gridKey;
		let _this = this;
		let cahce_key = key + "__qkcache";
		//store.remove(key);
		//console.log(key, cahce_key);


		//处理localdata去重
		let updatedata = _this.localdata;
		let uLen = updatedata.length;
		if (uLen > 1) {
			let prevData = [];
			prevData[0] = updatedata[0];
			for (let i = 1; i < uLen; i++) {
				let value = updatedata[i];
				let flag = true;
				for (let a = 0; a < prevData.length; a++) {
					let ditem = prevData[a];
					if (_this.matchOpt(value, ditem)) {
						prevData.splice(a, 1, value);
						flag = false; //如果已匹配重复，则后续无需再加
						break;
					}
				}
				if (flag) {
					prevData = prevData.concat(value);
				}

			}
			updatedata = prevData;

		}
		if (updatedata == null || updatedata.length == 0) {
			return;
		}
		_this.clearlocaldata(function () {
			localforage.setItem(cahce_key, updatedata).then(function () {
				func(cahce_key, updatedata);
			});
		});

		// localforage.getItem(key).then(function(readValue) {
		//     let updatedata = readValue;
		//     if(readValue==null || readValue.length==0){
		//         return;
		//     }
		//     //console.log(key, cahce_key,updatedata);
		//     _this.clearlocaldata(function(){
		//         localforage.setItem(cahce_key, updatedata).then(function () {
		//             func(cahce_key, updatedata);
		//         });
		//     });
		// });
	},
	clearcachelocaldata: function (func) {
		let key = this.gridKey;
		let cahce_key = key + "__qkcache";
		//store.remove(key);
		localforage.removeItem(cahce_key, function (err, value) {
			if (func && typeof (func) == "function") {
				func();
			}

		});
	},
	restorecachelocaldata: function (func) {
		let key = this.gridKey;
		let cahce_key = key + "__qkcache";
		let _this = this;
		localforage.getItem(cahce_key).then(function (readValue) {
			let updatedata = readValue;
			_this.getlocaldata(function (data) {
				if (data == null) {
					data = [];
				}
				let newdata = updatedata.concat(data);
				//data.unshift(updatedata);

				_this.localdata = newdata;
				if (func instanceof Function) {
					func(_this.localdata);
				}

				// localforage.setItem(key, newdata).then(function () {
				//     func(newdata);
				// }).catch(function (err) {

				// });
			});
		});
	},
	keepHighLightBox: function () {
		Store.cooperativeEdit.checkoutData.forEach(value => {
			if (value.index == Store.currentSheetIndex) {
				if (value.op === 'enterEdit') {
					server.multipleRangeShow(value.id, value.username, value.r, value.c, value.op);
				} else {
					server.multipleRangeShow(value.id, value.username, value.r, value.c);
				}
			}
		})
	}
}

export default server;
